package com.haotian.mail.client;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.event.TransportListener;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import org.apache.log4j.Logger;

public class _JavaMailClient implements AutoCloseable {

	private Logger log = Logger.getLogger(this.getClass());

	// 发送服务器地址
	private String host;
	// 用户名
	private String account;
	// 密码
	private String password;

	private Session mailSession;

	private boolean debug;

	private Transport tp;

	/**
	 * 
	 * @param host
	 *            地址
	 * @param account
	 *            用户
	 * @param password
	 *            密码
	 * @param debug
	 *            是否调式
	 * @param listener
	 *            监听 可实现 TransportListener 定义业务
	 * @throws MessagingException
	 */
	public _JavaMailClient(String host, String account, String password, boolean debug, TransportListener listener)
			throws MessagingException {
		this.host = host;
		this.account = account;
		this.password = password;
		this.debug = debug;
		this.mailSession = getSession();
		tp = this.mailSession.getTransport();
		if (this.account == null)
			tp.connect();
		else
			tp.connect(this.account, this.password);
		if (listener != null)
			tp.addTransportListener(listener);
	}

	private Session getSession() {
		// 发送邮件的环境属性
		final Properties props = new Properties();

		props.setProperty("mail.transport.protocol", "smtp");

		props.setProperty("mail.host", host);

		props.setProperty("mail.smtp.auth", null == account ? "false" : "true");// 请求身份认证
		Session mailSession;

		mailSession = Session.getInstance(props);
		if (this.debug) {
			mailSession.setDebug(true);
		}
		return mailSession;
	}

	public MimeMessage newMimeMessage(String fromUser, String sendToUser, String ccUser, String bccUser, InputStream in)
			throws MessagingException {

		MimeMessage message = null;

		if (null != in) {
			message = new MimeMessage(mailSession, in);
		} else {
			message = new MimeMessage(mailSession);
		}

		if (null != fromUser) {
			// 设置发件人
			InternetAddress iaformUser = new InternetAddress(fromUser);
			message.setFrom(iaformUser);
		}

		if (null != sendToUser) {
			// 设置收件人
			InternetAddress iatoUser = new InternetAddress(sendToUser);
			message.setRecipient(RecipientType.TO, iatoUser);
		} else if (null == in && null == sendToUser) {
			throw new MessagingException("501 Invalid Address");
		}
		if (null != ccUser) {
			// 设置抄送
			InternetAddress iaccUser = new InternetAddress(ccUser);
			message.setRecipient(RecipientType.CC, iaccUser);
		}
		if (null != bccUser) {
			// 设置密送，其他的收件人不能看到密送的邮件地址
			InternetAddress iabccUser = new InternetAddress(bccUser);
			message.setRecipient(RecipientType.BCC, iabccUser);
		}
		return message;
	}

	/**
	 * @Title: sendText
	 * @Description: 以文本形式发送邮件
	 * @param Title
	 *            邮件标题
	 * @param Text
	 *            邮件内容
	 * @param charset
	 *            文本编码
	 * @return boolean 返回类型
	 * @author 494009061@qq.com
	 * @throws MessagingException
	 * @date 2016年11月22日 上午11:28:07
	 */
	public void sendText(String fromUser, String sendToUse, String ccUser, String bccUser, String title, String Text,
			String charset) throws MessagingException {
		send(createTextMime(fromUser, sendToUse, ccUser, bccUser, title, Text, charset));
	}

	/**
	 * 
	 * @Title: sendHTML
	 * @Description: 以网页形式发送邮件
	 * @param content
	 *            网页内容
	 * @param charset
	 *            文本编码
	 * @return boolean 返回类型
	 * @author 494009061@qq.com
	 * @throws MessagingException
	 * @date 2016年11月22日 上午11:29:10
	 */
	public void sendHTML(String fromUser, String sendToUse, String ccUser, String bccUser, String title, String content,
			String charset) throws MessagingException {
		send(createHtmlMime(fromUser, sendToUse, ccUser, bccUser, title, content, charset));
	}

	/**
	 * 下发组装好的eml文件 直接转成mimeMessage 发送即可
	 *
	 * @author haotianrich@outlook.com
	 *         <p/>
	 * @date 2017年7月19日
	 * @param emlBuf
	 * @throws MessagingException
	 * @throws IOException
	 */
	public void sendEml(byte[] emlBuf) throws MessagingException, IOException {
		send(createByteMime(emlBuf));
	}

	/**
	 * 创建文本内容邮件的MimeMessage 对象
	 *
	 * @author haotianrich@outlook.com
	 *         <p/>
	 * @date 2017年7月20日
	 * @param fromUser
	 * @param sendToUse
	 * @param ccUser
	 * @param bccUser
	 * @param title
	 * @param Text
	 * @param charset
	 * @return
	 * @throws MessagingException
	 */
	public MimeMessage createTextMime(String fromUser, String sendToUse, String ccUser, String bccUser, String title,
			String Text, String charset) throws MessagingException {
		MimeMessage message = newMimeMessage(fromUser, sendToUse, ccUser, bccUser, null);
		// 设置邮件标题
		message.setSubject(title, charset);
		// 设置邮件的内容体
		message.setText(Text, charset);
		return message;
	}

	/**
	 * 利用mime 格式的 文件字节数组 创建 MimeMessage
	 *
	 * @author haotianrich@outlook.com
	 *         <p/>
	 * @date 2017年7月20日
	 * @param emlBuffer
	 * @return
	 * @throws MessagingException
	 * @throws IOException
	 */
	public MimeMessage createByteMime(byte[] emlBuffer) throws MessagingException, IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(emlBuffer);
		MimeMessage message = newMimeMessage(null, null, null, null, in);
		in.close();
		return message;
	}

	/**
	 * 创建HTML格式的邮件MimeMessage 对象
	 *
	 * @author haotianrich@outlook.com
	 *         <p/>
	 * @date 2017年7月20日
	 * @param fromUser
	 * @param sendToUse
	 * @param ccUser
	 * @param bccUser
	 * @param title
	 * @param content
	 * @param charset
	 * @return
	 * @throws MessagingException
	 */
	public MimeMessage createHtmlMime(String fromUser, String sendToUse, String ccUser, String bccUser, String title,
			String content, String charset) throws MessagingException {
		// 获取mime
		MimeMessage message = newMimeMessage(fromUser, sendToUse, ccUser, bccUser, null);
		// 创建一个Multipart 用于存储，存于HTML内容的 BodyPart
		Multipart mainPart = new MimeMultipart();
		// 创建一个包含HTML内容的MimeBodyPart
		BodyPart html = new MimeBodyPart();

		// html内容 存入 BodyPart
		html.setContent(content, "text/html; charset=" + charset);
		// BodyPart 存入 Multipart
		mainPart.addBodyPart(html);

		message.setSubject(title, charset);
		// Multipart 存入 消息中
		message.setContent(mainPart);
		return message;
	}

	/**
	 * 给传入的MimeMessage 加入附件，附件形式为java.io.File对象
	 * 
	 * MimeMessage 必须 加入过 MimeMultipart
	 * 
	 * @author haotianrich@outlook.com
	 *         <p/>
	 * @date 2017年7月19日
	 * @param message
	 * @param file
	 * @return
	 * @throws MessagingException
	 * @throws IOException
	 */
	public void setFileToMimeMessage(MimeMessage message, File file) throws MessagingException, IOException {

		Object o = message.getContent();

		if (o instanceof Multipart) {
			Multipart multipart = (Multipart) o;
			BodyPart attachmentBodyPart = new MimeBodyPart();
			DataSource source = new FileDataSource(file);
			attachmentBodyPart.setDataHandler(new DataHandler(source));
			attachmentBodyPart.setFileName(MimeUtility.encodeWord(file.getName()));
			multipart.addBodyPart(attachmentBodyPart);
			message.setContent(multipart);
		}
	}

	public synchronized void send(MimeMessage message) throws MessagingException {
		message.saveChanges();
		if (!tp.isConnected()) {

			if (log.isDebugEnabled())
				log.debug("host no connect , begin ReConnect!");

			if (this.account == null) {
				tp.connect();
			} else {
				tp.connect(this.account, this.password);
			}

		}
		tp.sendMessage(message, message.getAllRecipients());
	}

	public String errorCode(MessagingException e) {
		return e.getMessage().substring(0, 3);
	}

	public String errorMessage(MessagingException e) {
		return e.getMessage().substring(4);
	}

	public void close() {
		if (tp != null) {
			if (tp.isConnected()) {
				try {
					tp.close();
				} catch (MessagingException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@SuppressWarnings("resource")
	public static void main(String[] args) throws MessagingException {
		_JavaMailClient client = new _JavaMailClient("smtp.139.com", "18310451350@139.com", "fendou230184", true, null);
		client.sendText("18310451350@139.com","18310451350@139.com", null, null, "TestPDFText", "TestPDFText", "utf-8");
		
	}

}
